package cn.kmsoft.spatialboot.service.impl;

import cn.kmsoft.spatialboot.service.EllipsoidalService;
import cn.kmsoft.wololo.object.GeoJson;
import cn.kmsoft.wololo.object.GeoJsonFeature;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import cn.kmsoft.spatialboot.utils.EllipsoidalAreaCalculatorEx;
import cn.kmsoft.stgeometry.util.GeomUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author  wangq
 * @date 2022/12/28.
 */
@Service
public class EllipsoidalServiceImpl implements EllipsoidalService {
    private static final Logger logger = LoggerFactory.getLogger(EllipsoidalServiceImpl.class);

    private double centralMeridian = 105.0;//中央子午线
    private String sourceEPSG = "EPSG:4496";
    private String targetEPSG = "EPSG:4490";

    public double getCentralMeridian() {
        return centralMeridian;
    }
    public void setCentralMeridian(double centralMeridian) {
        this.centralMeridian = centralMeridian;
    }

    public String getSourceEPSG() {
        return sourceEPSG;
    }
    public void setSourceEPSG(String sourceEPSG) {
        this.sourceEPSG = sourceEPSG;
    }

    /**
     * 计算椭球面积
     * @param geoJson
     * @param digits
     * @return
     */
    @Override
    public GeoJson calcEllipsoidalArea(String geoJson, int digits) {
        List<GeoJsonFeature> outFeatures = new ArrayList<>();

        EllipsoidalAreaCalculatorEx calculator = new EllipsoidalAreaCalculatorEx(centralMeridian, sourceEPSG, targetEPSG);
        JSONArray inputFeatures = JSONObject.parseObject(geoJson).getJSONArray("features");
        for (int i = 0; i < inputFeatures.size(); i++) {
            GeoJsonFeature outFeature = new GeoJsonFeature();

            outFeature.setType("Feature");
            Map<String, Object> outProperties = new HashMap<>();
            JSONObject inputFeature = inputFeatures.getJSONObject(i);
            JSONObject inputGeometry = inputFeature.getJSONObject("geometry");
            JSONObject inputProperties = inputFeature.getJSONObject("properties");
            for (Object key : inputProperties.keySet()) {
                outProperties.put(key.toString(), inputProperties.get(key.toString()));
            }
            //椭球面积
            outProperties.put("TQMJ", calculator.getFeatureArea(GeomUtil.geojsonToWkt(inputGeometry.toString()), digits));
            outFeature.setProperties(outProperties);
            outFeatures.add(outFeature);
        }

        GeoJson outGeoJson = new GeoJson();
        if (outFeatures.size() > 0) {
            outGeoJson.setType("FeatureCollection");
            outGeoJson.setFeatures(outFeatures);
        }

        return outGeoJson;
    }

    /**
     * 计算平面面积
     * @param geoJson
     * @param digits
     * @return
     */
    @Override
    public GeoJson calcPlaneArea(String geoJson, int digits) {
        List<GeoJsonFeature> outFeatures = new ArrayList<>();

        //采用cgcs2000坐标系
        EllipsoidalAreaCalculatorEx calculator = new EllipsoidalAreaCalculatorEx(centralMeridian, sourceEPSG, targetEPSG);
        JSONArray inputFeatures = JSONObject.parseObject(geoJson).getJSONArray("features");
        for (int i = 0; i < inputFeatures.size(); i++) {
            GeoJsonFeature outFeature = new GeoJsonFeature();
            outFeature.setType("Feature");
            Map<String, Object> outProperties = new HashMap<>();
            JSONObject inputFeature = inputFeatures.getJSONObject(i);
            JSONObject inputGeometry = inputFeature.getJSONObject("geometry");
            JSONObject inputProperties = inputFeature.getJSONObject("properties");
            for (Object key : inputProperties.keySet()) {
                outProperties.put(key.toString(), inputProperties.get(key.toString()));
            }
            //平面面积
            outProperties.put("PMMJ", calculator.getFeatureArea2(GeomUtil.geojsonToWkt(inputGeometry.toString()), digits));
            outFeature.setProperties(outProperties);
            outFeatures.add(outFeature);
        }

        GeoJson outGeoJson = new GeoJson();
        if (outFeatures.size() > 0) {
            outGeoJson.setType("FeatureCollection");
            outGeoJson.setFeatures(outFeatures);
        }

        return outGeoJson;
    }
}
